use rand::random;
use ylong_runtime::net::TcpStream;

use crate::common::hdc_error::{HdcError, HdcErrorKind};
use crate::common::tcp_connect::TcpConnect;
use crate::server::stub;

use super::stub::Stub;

pub struct Proxy {
    pub stub: Stub,
    pub client: TcpConnect,
}

impl Proxy {
    pub async fn new(client_stream: TcpStream) -> Option<Self> {
        let client = TcpConnect::new(client_stream);
        // 需要将生成的channel_id发送给client，后续所有的包都需要填充channel_id, 用于usb接收到的数据分发
        let _channel_id = random::<u32>();

        // todo connect_key 需要从对端获取
        let connect_key = "any".to_owned();
        let Ok(stub) = stub::session::get_stub(&connect_key).await else {
            log::error!("Get stub failed");
            return None;
        };

        Some(Self { stub, client})
    }

    pub async fn run_task(&mut self) -> Result<(), HdcError> {
        ylong_runtime::select! {
            msg = self.stub.read() => {
                match msg {
                    Ok(msg)=>{
                        log::info!("send to client, {msg:?}");
                        let _ = self.client.write_message(msg).await;
                        Ok(())
                    },
                    Err(err) => {
                        log::error!("{err:?}");
                        Err(err)
                    },
                }
            },
            msg = self.client.read_msg() => {
                match msg {
                    Ok(msg)=>{
                        // log::info!("msg {:?}", msg);
                        // 任务分发
                        let _ = self.stub.write(msg).await;
                        Ok(())
                    },
                    Err(err) if err.kind == HdcErrorKind::HdcInvalidData => {
                        Ok(())
                    },
                    Err(err) => {
                        log::error!("{err:?}");
                        Err(err)
                        // Ok(())
                    },
                }
            },
        }
    }
}

impl Drop for Proxy {
    fn drop(&mut self) {
        log::info!("drop Proxy");
    }
}
